package com.jeesit.cloud.spot.web.interceptor;

import com.yomahub.tlog.constant.TLogConstants;
import com.yomahub.tlog.context.SpanIdGenerator;
import com.yomahub.tlog.context.TLogContext;
import com.yomahub.tlog.spring.TLogSpringAware;
import com.yomahub.tlog.utils.LocalhostUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.Buffer;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * @description: okhttp日志拦截器，调用openFeign接口时,打印日志
 * @author: syd
 * @create: 2023/5/4 22:54
 */
@Slf4j
public class OkHttpLoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        String traceId = TLogContext.getTraceId();
        if (StringUtils.isNotBlank(traceId)) {
            String appName = TLogSpringAware.getProperty("spring.application.name");
            Request.Builder builder = request.newBuilder();
            builder.header(TLogConstants.TLOG_TRACE_KEY, traceId);
            builder.header(TLogConstants.TLOG_SPANID_KEY, SpanIdGenerator.generateNextSpanId());
            builder.header(TLogConstants.PRE_IVK_APP_KEY, appName);
            builder.header(TLogConstants.PRE_IVK_APP_HOST, LocalhostUtil.getHostName());
            builder.header(TLogConstants.PRE_IP_KEY, LocalhostUtil.getHostIp());
            request = builder.build();
        } else {
            log.debug("[TLOG]本地threadLocal变量没有正确传递traceId,本次调用不传递traceId");
        }
        long t1 = System.nanoTime();
        RequestBody requestBody = request.body();
        Buffer buffer = new Buffer();
        String requestString = "";
        try {
            requestBody.writeTo(buffer);
            Charset charset = Charset.forName("UTF-8");
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(Charset.forName("UTF-8"));
            }
            //拿到request
            requestString  = buffer.readString(charset);
        } catch (Exception e) {
            log.warn("{}", e.getMessage());
        }
        log.info(String.format("发送请求 >>> %s on %s%n%s", request.url(), requestString, request.headers()));
        Response response = chain.proceed(request);
        long t2 = System.nanoTime();
        //这里不能直接使用response.body().string()的方式输出日志
        //因为response.body().string()之后，response中的流会被关闭，程序会报错，我们需要创建出一个新的response给应用层处理
        ResponseBody responseBody = response.peekBody(1024 * 1024);
//        log.info("<<< 接收url: {}", response.request().url());
//        log.info("<<< 响应header: {}", response.headers());
        log.info("<<< 返回信息: {}", responseBody.string());
        log.info("<<< 调用耗时: {}ms", (t2 - t1) / 1e6d);
        return response;
    }
}
